package com.itheima.tanhua.service;

import com.itheima.tanhua.api.UserApi;
import com.itheima.tanhua.api.UserLikeApi;
import com.itheima.tanhua.autoconfig.template.HuanXinTemplate;
import com.itheima.tanhua.autoconfig.template.SMSTemplate;
import com.itheima.tanhua.domain.User;
import com.itheima.tanhua.enums.LogType;
import com.itheima.tanhua.exception.BusinessException;
import com.itheima.tanhua.utils.Constants;
import com.itheima.tanhua.utils.JwtUtils;
import com.itheima.tanhua.utils.UserHolder;
import com.itheima.tanhua.vo.CountsVo;
import com.itheima.tanhua.vo.ErrorResult;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Lff
 * @date 2022/3/22
 */
@Service
public class UserService {

    private static final String CHECK_CODE_PREF = "CHECK_CODE_";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SMSTemplate sms;

    @DubboReference
    private UserApi userApi;

    @Autowired
    private HuanXinTemplate hx;

    @Autowired
    private MqMessageService mq;

    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private UserFreezeService userFreezeService;

    /**
     * 生成并且发送验证码
     *
     * @param phone
     */
    public void sendMsg(String phone) {
        //根据手机查询用户
        User mobile = userApi.findByMobile(phone);
        //校验用户状态
        if (mobile != null) {
            userFreezeService.checkUserStatus("1", mobile.getId());
        }
        /*if (phone == null) {
            //内存中获取手机号
            phone = UserHolder.getUser().getMobile();
        }*/
        //1. 生成六位随机数
        String code = RandomStringUtils.randomNumeric(6);
        //2. 发送验证码
//        sms.sendMessage(phone,code);
        sms.testSms(phone, code);
        //3. 保存到redis中 5 分钟有效
        redisTemplate.opsForValue().set(CHECK_CODE_PREF + phone, code, Duration.ofMinutes(5));
    }

    /**
     * 用户登录
     *
     * @param phone
     * @param verificationCode
     * @return
     */
    public Map loginVerification(String phone, String verificationCode) {
        //获取验证码并校验
        String code = (String) redisTemplate.opsForValue().get(CHECK_CODE_PREF + phone);
        if (!this.checkVerificationCode(phone, verificationCode)) {
            //验证码错误
            throw new BusinessException(ErrorResult.verificationCodeError());
        }
        //根据手机号查询用户
        User user = userApi.findByMobile(phone);
        //用户不存在创建新用户
        boolean isNew = false;
        if (user == null) {
            user = new User();
            //设置基础信息
            user.setMobile(phone);
            //密码加密
            user.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
            Long id = userApi.save(user);
            user.setId(id);
            System.err.println("::::::::::::::::用户不存在，注册！::::::::::::::::");
            isNew = true;
        }
        if (!checkHxUser(user)) {
            //不存在环信用户状态
            //注册集成环信
            String hxUser = "hx" + user.getId();
            String hxPassword = "123456";
            //创建环信账号
            Boolean isSuccess = hx.createUser(hxUser, hxPassword);
            if (isSuccess) {
                user.setHxUser(hxUser);
                user.setHxPassword(hxPassword);
            }
            //更新环信信息
            userApi.updateById(user);
        }
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("id", user.getId());
        tokenMap.put("phone", phone);
        //封装token
        String token = JwtUtils.getToken(tokenMap);
        //返回Map
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("token", token);
        resultMap.put("isNew", isNew);
        //token加入到缓存中
        redisTemplate.opsForValue().set("token", token, Duration.ofMinutes(90));

        //记录日志
        String type = "";
        if (isNew) {
            //新用户
            type = LogType.LOG_TYPE_REGISTER.getValue();
        } else {
            type = LogType.LOG_TYPE_LOGIN.getValue();
        }
        //发送消息
        mq.sendLogMessage(user.getId(), type, "user", null);
        return resultMap;
    }

    /**
     * 检验验证码
     *
     * @param mobile
     * @param verificationCode
     * @return
     */
    public boolean checkVerificationCode(String mobile, String verificationCode) {
        if (mobile == null) {
            //缓存里获取手机号
            mobile = UserHolder.getUser().getMobile();
        }
        //获取验证码并校验
        String code = (String) redisTemplate.opsForValue().get(CHECK_CODE_PREF + mobile);
        boolean flag = StringUtils.isEmpty(code) || !"123456".equals(verificationCode);//code
        if (!flag) {
            //验证码正确的 删除缓存
            redisTemplate.delete(CHECK_CODE_PREF + mobile);
        }
        return !flag;
    }

    /**
     * 修改手机号
     *
     * @param phone
     */
    public void upMobile(String phone) {
        //获取用户id 填充User
        User user = UserHolder.getUser();
        user.setMobile(phone);
        //调用api修改
        userApi.updateById(user);
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("id", user.getId());
        tokenMap.put("phone", phone);
        //封装token
        String token = JwtUtils.getToken(tokenMap);
        //存储新的token 不用设置过期时间
        redisTemplate.opsForValue().set("newToken", token);
    }

    /**
     * 检验用户的环信状态
     *
     * @param user
     * @return
     */
    private boolean checkHxUser(User user) {
        return !(user.getHxUser() == null || user.getHxUser().equals(""));
    }

    /**
     * 统计各种数量
     *
     * @return
     */
    public CountsVo findCounts() {
        //获取当前登录用户id
        Long id = UserHolder.getUser().getId();
        CountsVo c = userLikeApi.findCounts(id);
        return c;
    }


    /**
     * 判断用户是否喜欢
     *
     * @param uid
     * @return
     */
    public boolean checkAlreadyLove(Long uid) {
        if (redisTemplate.opsForSet().isMember(Constants.USER_LIKE_SET + UserHolder.getUser().getId(), uid.toString())) {
            return true;
        }
        if (userLikeApi.checkAlreadyLove(UserHolder.getUser().getId(), uid)) {
            //缓存里没有，数据库有，添加到缓存
            redisTemplate.opsForSet().add(Constants.USER_LIKE_SET + UserHolder.getUser().getId(), uid.toString());
            redisTemplate.opsForSet().remove(Constants.USER_DISLIKE_SET + UserHolder.getUser().getId(), uid.toString());
            return true;
        }
        return false;
    }
}
